import React from 'react'
import { TreeNode, createResource } from '@designable/core'
import {
  useTreeNode,
  TreeNodeWidget,
  DroppableWidget,
  useNodeIdProps,
  DnFC,
} from '@designable/react'
import { ArrayBase } from '@formily/antd'
import { observer } from '@formily/react'
import { LoadTemplate } from '../../common/LoadTemplate'
import { useDropTemplate } from '../../hooks'
import {
  hasNodeByComponentPath,
  queryNodesByComponentPath,
  createEnsureTypeItemsNode,
  findNodeByComponentPath,
  createNodeId,
} from '../../shared'
import { createArrayBehavior } from '../ArrayBase'
import cls from 'classnames'
import './styles.less'

const ensureObjectItemsNode = createEnsureTypeItemsNode('object')

const isArrayTabsOperation = (name: string) =>
  name === 'ArrayTabs.Remove' || name === 'ArrayTabs.SortHandle'

export const ArrayTabs: DnFC<React.HTMLAttributes<HTMLDivElement>> = observer(
  (props) => {
    const node = useTreeNode()
    const nodeId = useNodeIdProps()
    const designer = useDropTemplate('ArrayTabs', (source) => {
      const sortHandleNode = new TreeNode({
        componentName: node.componentName,
        props: {
          type: 'void',
          'x-component': 'ArrayTabs.SortHandle',
        },
      })
      const removeNode = new TreeNode({
        componentName: node.componentName,
        props: {
          type: 'void',
          title: 'Remove',
          'x-component': 'ArrayTabs.Remove',
        },
      })

      const objectNode = new TreeNode({
        componentName: node.componentName,
        props: {
          type: 'object',
        },
        children: [sortHandleNode, ...source, removeNode],
      })
      const additionNode = new TreeNode({
        componentName: node.componentName,
        props: {
          type: 'void',
          title: '新增',
          'x-component': 'ArrayTabs.Addition',
        },
      })
      return [objectNode, additionNode]
    })
    const renderItems = () => {
      if (node.children.length === 0) return <DroppableWidget />
      const additions = queryNodesByComponentPath(node, [
        'ArrayTabs',
        'ArrayTabs.Addition',
      ])
      const sortHandles = queryNodesByComponentPath(node, [
        'ArrayTabs',
        '*',
        'ArrayTabs.SortHandle',
      ])
      const operations = queryNodesByComponentPath(node, [
        'ArrayTabs',
        '*',
        isArrayTabsOperation,
      ])
      const children = queryNodesByComponentPath(node, [
        'ArrayTabs',
        '*',
        (name) => name.indexOf('ArrayTabs.') === -1,
      ])
      return (
        <ArrayBase disabled>
          <ArrayBase.Item index={0} record={null}>
            <div
              {...props}
              className={cls('ant-formily-array-tabs-item', props.className)}
            >
              <div {...createNodeId(designer, ensureObjectItemsNode(node).id)}>
                {sortHandles.map((node) => (
                  <TreeNodeWidget key={node.id} node={node} />
                ))}
                {children.length ? (
                  children.map((node) => (
                    <TreeNodeWidget key={node.id} node={node} />
                  ))
                ) : (
                  <DroppableWidget hasChildren={false} />
                )}
                {operations
                  .filter(
                    (node) => node.props['x-component'] === 'ArrayTabs.Remove'
                  )
                  .map((node) => (
                    <TreeNodeWidget key={node.id} node={node} />
                  ))}
              </div>
            </div>
          </ArrayBase.Item>
          {additions.map((node) => (
            <TreeNodeWidget key={node.id} node={node} />
          ))}
        </ArrayBase>
      )
    }

    return (
      <div {...nodeId} className="dn-array-tabs">
        {renderItems()}
        <LoadTemplate
          actions={[
            {
              title: node.getMessage('addIndex'),
              icon: 'AddIndex',
              onClick: () => {
                if (
                  hasNodeByComponentPath(node, [
                    'ArrayTabs',
                    '*',
                    'ArrayTabs.SortHandle',
                  ])
                )
                  return
                const sortHandleNode = new TreeNode({
                  componentName: node.componentName,
                  props: {
                    type: 'void',
                    'x-component': 'ArrayTabs.SortHandle',
                  },
                })
                ensureObjectItemsNode(node).prepend(sortHandleNode)
              },
            },
            {
              title: node.getMessage('addOperation'),
              icon: 'AddOperation',
              onClick: () => {
                const oldAdditionNode = findNodeByComponentPath(node, [
                  'ArrayTabs',
                  'ArrayTabs.Addition',
                ])
                if (!oldAdditionNode) {
                  const additionNode = new TreeNode({
                    componentName: node.componentName,
                    props: {
                      type: 'void',
                      title: 'Addition',
                      'x-component': 'ArrayTabs.Addition',
                    },
                  })
                  ensureObjectItemsNode(node).insertAfter(additionNode)
                }
                const oldRemoveNode = findNodeByComponentPath(node, [
                  'ArrayTabs',
                  '*',
                  'ArrayTabs.Remove',
                ])
                if (!oldRemoveNode) {
                  ensureObjectItemsNode(node).append(
                    new TreeNode({
                      componentName: node.componentName,
                      props: {
                        type: 'void',
                        'x-component': 'ArrayTabs.Remove',
                      },
                    })
                  )
                }
              },
            },
          ]}
        />
      </div>
    )
  }
)

ArrayBase.mixin(ArrayTabs)

ArrayTabs.Behavior = createArrayBehavior('ArrayTabs')

ArrayTabs.Resource = createResource({
  icon: 'ArrayCardsSource',
  elements: [
    {
      componentName: 'Field',
      props: {
        type: 'array',
        'x-decorator': 'FormItem',
        'x-component': 'ArrayTabs',
      },
    },
  ],
})
